package cz.cuni.amis.episodic.bayes.experiment;

import cz.cuni.amis.episodic.bayes.memories.IntervalSurpriseMemoryCreator;
import cz.cuni.amis.episodic.bayes.memories.MemoryCreator;
import cz.cuni.amis.episodic.bayes.memories.MinimizeKLMemoryCreator;
import cz.cuni.amis.episodic.bayes.memories.PointSurpriseMemoryCreator;
import cz.cuni.amis.episodic.bayes.utils.chart.AgregateGraphDevice;
import cz.cuni.amis.episodic.bayes.utils.chart.GraphPaintingDevice;
import cz.cuni.amis.episodic.bayes.utils.chart.PdfGraphDevice;
import cz.cuni.amis.episodic.bayes.utils.chart.PngGraphDevice;
import cz.cuni.amis.episodic.lisp.DefaultLispTranslator;
import cz.cuni.amis.episodic.lisp.LispPlanToCsvData;
import cz.cuni.amis.episodic.lisp.behan.LispTree;
import cz.cuni.amis.episodic.lisp.behan.TraceToEventVisitor;
import cz.cuni.amis.episodic.lisp.netcreators.AHMEMCreator;
import cz.cuni.amis.episodic.lisp.netcreators.CHMMCreator;
import cz.cuni.amis.episodic.lisp.netcreators.DayPaddingStrategy;
import cz.cuni.amis.episodic.lisp.netcreators.HHMMCreator;
import cz.cuni.amis.episodic.lisp.netcreators.HHMMMurphyPaskin2001Creator;
import cz.cuni.amis.episodic.lisp.netcreators.NetCreator;
import cz.cuni.amis.episodic.lisp.netcreators.StrategySequence;
import cz.cuni.amis.episodic.lisp.netcreators.TraceModificationStrategy;
import cz.cuni.amis.episodic.lisp.netcreators.UpperTraceAndObservationStrategy;
import cz.cuni.amis.episodic.lisp.netcreators.UpperTraceStrategy;
import cz.cuni.amis.episodic.lisp.visitor.TreeTraceVisitor;

import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import smile.Network.BayesianAlgorithmType;

/**
 * Experiments with Pogamut domain.
 * @author rk
 */
public class Experiment_9_cermak extends LispExperiment {

	@Override
	protected GraphPaintingDevice createGraphDevice(File rootDir) {
		int width = 700;
		// good for observations 
		//int height = 600;
		// good for episodes 
		int height = 400;
		//int height = 100;
		return new AgregateGraphDevice(new GraphPaintingDevice[] {
		new PdfGraphDevice(rootDir, width, height),
		new PngGraphDevice(rootDir,  width, height) }, rootDir);
	}

	protected MemoryCreator[] createMemoryCreators(GraphPaintingDevice device) {
		return new MemoryCreator[] { new IntervalSurpriseMemoryCreator(device)};
		
				//, new MinimizeKLMemoryCreator(device) };
	}

	DayPaddingStrategy<String> cermakPogamutStrategy = new DayPaddingStrategy<String>(
			"ISleep", new String[] { "DAY_END" });

	public Experiment_9_cermak() {
		super("9_cermak", new File("target/experiments"), new File(
				"../datasets/9_cermak"), "Cermak_pogamut3.lisp");

		networkFilenames = new String[] {};
		batchSize = 36;
		//createAndLearnNetworks = true;
		createAndLearnNetworks = true;
		drawMemoryCreationGraphs = true;
		//bayesianAlgorithmType = BayesianAlgorithmType.Lauritzen;
		//bayesianAlgorithmType = BayesianAlgorithmType.EpisSampling;
		//numberOfSamplesInApproximation = 20000;
		performEvolutionExample = true;
		
		
		memsCreatedNum = 9;

		setTrainingDataRange(new int[] {0,22});
		setTestingDataRange(new int[] {21,22});
		
		TraceModificationStrategy level1 = new StrategySequence(
				new TraceModificationStrategy[] { cermakPogamutStrategy,
						new UpperTraceAndObservationStrategy(1) });
		TraceModificationStrategy level2 = new StrategySequence(
				new TraceModificationStrategy[] { cermakPogamutStrategy,
						new UpperTraceAndObservationStrategy(2) });
		TraceModificationStrategy level4 = new UpperTraceAndObservationStrategy(
				4);

		networkCreators = Arrays.asList(
				new CHMMCreator(true, level1),
		//		new CHMMCreator(true, level2)
		// new CHMMCreator(true, level4),
		   new AHMEMCreator(2, level1, true)
		// new AHMEMCreator(2, level2, true)
		// new AHMEMCreator(4, level1, true),
		// new AHMEMCreator(4, level2, true)
		// new AHMEMCreator(8, level1, true)
		// new AHMEMCreator(8, level2, true)
		);

	}

	public static void main(String[] args) throws Exception {
		Experiment e = new Experiment_9_cermak();
		e.perform();
	}

	@Override
	public List<List<String>> getTestCases() {
		LispTree parser = new LispTree(inputLispPlan.getAbsolutePath());
		LispPlanToCsvData.LispToCsvResult res = new LispPlanToCsvData.LispToCsvResult();
		LispPlanToCsvData.TreeToTraceTranslator translator = new LispPlanToCsvData.BehanFilteredProcessor(
				10);
		parser.walkInForest(new TraceToEventVisitor(null, null, null,
				translator));

		// TODO strategy should be passed to translator ...
		List<String[]> traces = cermakPogamutStrategy.modifyTrace(
				translator.getTraces(), true);

		final List<String> evidence = new LinkedList<>();

		for (String[] trace : traces) {
			evidence.add(trace[trace.length - 1]);
		}
		
		// split
		
		return split(evidence, batchSize).subList(22, 23);
		//return split(evidence, batchSize).subList(19, 20);
	}
	
}
